using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics.Contracts;
using Konst3d.Efficiency.IO;

// LAYOUT:
// signature     4b (uint)    0
// version       4b (uint)    4
// ID            4b (int)     8
// created year  4b (int)    12
// created month 1b (byte)   16
// created day   1b (byte)   17
// titleID       4b (int)    18
// descrID       4b (int)    22

namespace Konst3d.Efficiency.Suite.SparsedBinary
{
    internal class MonitoringGroupFile : BinaryFile
    {
        #region Constants

        private const uint SIGNATURE = 0x75757575;
        private const uint VERSION = 1;
        private const int OFFSET_ID = 8;
        private const int OFFSET_CREATED_YEAR = 12;
        private const int OFFSET_CREATED_MONTH = 16;
        private const int OFFSET_CREATED_DAY = 17;
        private const int OFFSET_TITLE_ID = 18;
        private const int OFFSET_DESCR_ID = 22;

        #endregion // Constants

        #region Properties

        public int ID
        {
            get
            {
                return _id;
            }
            set
            {
                _writer.Write(value, OFFSET_ID);
                _id = value;
            }
        }

        public int TitleID
        {
            get
            {
                return _titleID;
            }
            set
            {
                _writer.Write(value, OFFSET_TITLE_ID);
                _titleID = value;
            }
        }

        public int DescrID
        {
            get
            {
                return _descrID;
            }
            set
            {
                _writer.Write(value, OFFSET_DESCR_ID);
                _descrID = value;
            }
        }

        public DateTime Created
        {
            get
            {
                return _created;
            }
            set
            {
                _writer.WriteShortDate(value, OFFSET_CREATED_YEAR);
                _created = value;
            }
        }

        #endregion // Properties

        #region Create/Open Methods

        public static MonitoringGroupFile Create(string path, bool overwrite, ICryptographicEngine cryptographicEngine, DateTime created, int titleID, int descrID, int id)
        {
            Contract.Requires(!String.IsNullOrEmpty(path));
            Contract.Requires(cryptographicEngine != null);

            if (File.Exists(path) && !overwrite)
            {
                throw new IOException(String.Format("File \"{0}\" is already exists.", path));
            }

            FileStream stream = null;
            BinaryReader reader = null;
            BinaryWriter writer = null;

            try
            {
                stream = File.Open(path, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
                reader = new BinaryReader(stream, cryptographicEngine.Encoding);
                writer = new BinaryWriter(stream, cryptographicEngine.Encoding);

                writer.Write(SIGNATURE);
                writer.Write(VERSION);
                writer.Write(id);
                writer.WriteShortDate(created);
                writer.Write(titleID);
                writer.Write(descrID);

                writer.Flush();
                writer.Seek(0, SeekOrigin.Begin);

                return new MonitoringGroupFile(stream, reader, writer, cryptographicEngine);
            }
            catch
            {
                if (stream != null)
                {
                    stream.Dispose();
                }

                if (reader != null)
                {
                    reader.Dispose();
                }

                if (writer != null)
                {
                    writer.Dispose();
                }

                throw;
            }
        }

        public static MonitoringGroupFile Open(string path, ICryptographicEngine cryptographicEngine)
        {
            Contract.Requires(!String.IsNullOrEmpty(path));
            Contract.Requires(File.Exists(path));
            Contract.Requires(cryptographicEngine != null);

            FileStream stream = null;
            BinaryReader reader = null;
            BinaryWriter writer = null;

            try
            {
                stream = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
                reader = new BinaryReader(stream, cryptographicEngine.Encoding);
                writer = new BinaryWriter(stream, cryptographicEngine.Encoding);

                return new MonitoringGroupFile(stream, reader, writer, cryptographicEngine);
            }
            catch
            {
                if (stream != null)
                {
                    stream.Dispose();
                }

                if (reader != null)
                {
                    reader.Dispose();
                }

                if (writer != null)
                {
                    writer.Dispose();
                }

                throw;
            }
        }

        #endregion // Create/Open Methods

        #region Constructor

        private MonitoringGroupFile(FileStream stream, BinaryReader reader, BinaryWriter writer, ICryptographicEngine cryptographicEngine) :
            base(stream, reader, writer, SIGNATURE, VERSION)
        {
            Contract.Requires(cryptographicEngine != null);

            _cryptographicEngine = cryptographicEngine;

            _id      = _reader.ReadInt32();
            _created = _reader.ReadShortDate().GetDateTime();
            _titleID = _reader.ReadInt32();
            _descrID = _reader.ReadInt32();
        }

        #endregion // Constructor

        #region Fields

        private ICryptographicEngine _cryptographicEngine;
        private int _id = 0;
        private DateTime _created;
        private int _titleID;
        private int _descrID;

        #endregion // Fields
    }
}
